/*
 *   Copyright 1999-2018 dragonshard.net.
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *        http://www.apache.org/licenses/LICENSE-2.0
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package net.dragonshard.dsf.web.core.wrapper;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import net.dragonshard.dsf.core.toolkit.ObjectUtils;
import net.dragonshard.dsf.web.core.framework.util.RequestUtils;
import org.springframework.web.util.HtmlUtils;

/**
 * Request包装类
 * <p>
 * 1.预防xss攻击 2.拓展requestbody无限获取(HttpServletRequestWrapper只能获取一次)
 * </p>
 *
 * @author Caratacus
 */
public class RequestWrapper extends HttpServletRequestWrapper {

  /**
   * 存储requestBody byte[]
   */
  private final byte[] body;

  public RequestWrapper(HttpServletRequest request) {
    super(request);
    this.body = RequestUtils.getByteBody(request);
  }

  @Override
  public BufferedReader getReader() {
    return ObjectUtils.isEmpty(body) ? null
      : new BufferedReader(new InputStreamReader(getInputStream()));
  }

  @Override
  public ServletInputStream getInputStream() {
    final ByteArrayInputStream bais = new ByteArrayInputStream(body);
    return getServletInputStream(bais);
  }

  private ServletInputStream getServletInputStream(ByteArrayInputStream bais) {
    return new ServletInputStream() {

      @Override
      public boolean isFinished() {
        return false;
      }

      @Override
      public boolean isReady() {
        return false;
      }

      @Override
      @SuppressWarnings("EmptyMethod")
      public void setReadListener(ReadListener readListener) {

      }

      @Override
      public int read() {
        return bais.read();
      }
    };
  }

  @Override
  public String[] getParameterValues(String name) {
    String[] values = super.getParameterValues(name);
    if (values == null) {
      return null;
    }
    int count = values.length;
    String[] encodedValues = new String[count];
    for (int i = 0; i < count; i++) {
      encodedValues[i] = htmlEscape(values[i]);
    }
    return encodedValues;
  }

  @Override
  public String getParameter(String name) {
    String value = super.getParameter(name);
    if (value == null) {
      return null;
    }
    return htmlEscape(value);
  }

  @Override
  public Object getAttribute(String name) {
    Object value = super.getAttribute(name);
    if (value instanceof String) {
      htmlEscape((String) value);
    }
    return value;
  }

  @Override
  public String getHeader(String name) {
    String value = super.getHeader(name);
    if (value == null) {
      return null;
    }
    return htmlEscape(value);
  }

  @Override
  public String getQueryString() {
    String value = super.getQueryString();
    if (value == null) {
      return null;
    }
    return htmlEscape(value);
  }

  /**
   * 使用spring HtmlUtils 转义html标签达到预防xss攻击效果
   *
   * @param str 参数
   * @see org.springframework.web.util.HtmlUtils#htmlEscape
   */
  private String htmlEscape(String str) {
    return HtmlUtils.htmlEscape(str);
  }

}
